Handle page overlapping copies.
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 2 Sep 2005 17:53:04 +0000 (17:53 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 2 Sep 2005 17:53:04 +0000 (17:53 +0000)
Signed-Off-By: Leendert van Doorn <leendert@watson.ibm.com>
xen/arch/x86/vmx.c
xen/include/asm-x86/vmx.h

index 6621b0bafe623162598ec26ecaf07a3f21245269..b192bb05e6be8164dcd845963846b12f7f0b0103 100644 (file)
@@ -699,29 +699,34 @@ static void vmx_io_instruction(struct cpu_user_regs *regs,
     vmx_wait_io();
 }
 
-enum { COPY_IN = 0, COPY_OUT };
-
-static inline int
+int
 vmx_copy(void *buf, unsigned long laddr, int size, int dir)
 {
-    char *addr;
     unsigned long mfn;
+    char *addr;
+    int count;
 
-    if ( (size + (laddr & (PAGE_SIZE - 1))) >= PAGE_SIZE )
-    {
-       printf("vmx_copy exceeds page boundary\n");
-        return 0;
-    }
+    while (size > 0) {
+       count = PAGE_SIZE - (laddr & ~PAGE_MASK);
+       if (count > size)
+           count = size;
 
-    mfn = get_mfn_from_pfn(laddr >> PAGE_SHIFT);
-    addr = (char *)map_domain_page(mfn) + (laddr & ~PAGE_MASK);
+       mfn = get_mfn_from_pfn(laddr >> PAGE_SHIFT);
+       /* XXX check whether laddr is valid */
+       addr = (char *)map_domain_page(mfn) + (laddr & ~PAGE_MASK);
 
-    if (dir == COPY_IN)
-           memcpy(buf, addr, size);
-    else
-           memcpy(addr, buf, size);
+       if (dir == VMX_COPY_IN)
+           memcpy(buf, addr, count);
+       else
+           memcpy(addr, buf, count);
+
+       unmap_domain_page(addr);
+
+       laddr += count;
+       buf += count;
+       size -= count;
+    }
 
-    unmap_domain_page(addr);
     return 1;
 }
 
@@ -908,7 +913,7 @@ vmx_assist(struct vcpu *d, int mode)
     u32 cp;
 
     /* make sure vmxassist exists (this is not an error) */
-    if (!vmx_copy(&magic, VMXASSIST_MAGIC_OFFSET, sizeof(magic), COPY_IN))
+    if (!vmx_copy(&magic, VMXASSIST_MAGIC_OFFSET, sizeof(magic), VMX_COPY_IN))
        return 0;
     if (magic != VMXASSIST_MAGIC)
        return 0;
@@ -922,20 +927,20 @@ vmx_assist(struct vcpu *d, int mode)
      */
     case VMX_ASSIST_INVOKE:
        /* save the old context */
-       if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), COPY_IN))
+       if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), VMX_COPY_IN))
            goto error;
        if (cp != 0) {
            if (!vmx_world_save(d, &c))
                goto error;
-           if (!vmx_copy(&c, cp, sizeof(c), COPY_OUT))
+           if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_OUT))
                goto error;
        }
 
        /* restore the new context, this should activate vmxassist */
-       if (!vmx_copy(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp), COPY_IN))
+       if (!vmx_copy(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp), VMX_COPY_IN))
            goto error;
        if (cp != 0) {
-            if (!vmx_copy(&c, cp, sizeof(c), COPY_IN))
+            if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_IN))
                goto error;
            if (!vmx_world_restore(d, &c))
                goto error;
@@ -949,10 +954,10 @@ vmx_assist(struct vcpu *d, int mode)
      */
     case VMX_ASSIST_RESTORE:
        /* save the old context */
-       if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), COPY_IN))
+       if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), VMX_COPY_IN))
            goto error;
        if (cp != 0) {
-            if (!vmx_copy(&c, cp, sizeof(c), COPY_IN))
+            if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_IN))
                goto error;
            if (!vmx_world_restore(d, &c))
                goto error;
index 1d9b74dfb5517de32d6ac3e24d834b4591e6b435..c03559849f1e94a285dbc23d2152c94176b9e1ae 100644 (file)
@@ -471,4 +471,7 @@ static inline int iopacket_port(struct domain *d)
 void load_cpu_user_regs(struct cpu_user_regs *regs);
 void store_cpu_user_regs(struct cpu_user_regs *regs);
 
+enum { VMX_COPY_IN = 0, VMX_COPY_OUT };
+int vmx_copy(void *buf, unsigned long laddr, int size, int dir);
+
 #endif /* __ASM_X86_VMX_H__ */